/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by Wangyunlai on 2022/5/22.
//

#pragma once

#include "sql/expr/expression.h"
#include "sql/parser/parse_defs.h"
#include "sql/stmt/stmt.h"
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

class Db;
class Table;
class FieldMeta;

struct FilterObj
{
  bool is_attr;
  // Field                       field;
  // Value                       value;
  std::unique_ptr<Expression> obj_expr;
  std::unique_ptr<Expression> simple_sub_query;
  std::unique_ptr<Expression> tuple_values;

  // void init_attr(const Field &field)
  // {
  //   is_attr     = true;
  //   this->field = field;
  // }
  //
  // void init_value(const Value &value)
  // {
  //   is_attr     = false;
  //   this->value = value;
  // }
  void init_obj_expr(std::unique_ptr<Expression> &&expr)
  {
    is_attr  = false;
    obj_expr = std::move(expr);
  }

  void init_sub_query(std::unique_ptr<Expression> &&sub_query)
  {
    is_attr          = false;
    simple_sub_query = std::move(sub_query);
  }

  void init_tuple_values(std::unique_ptr<Expression> &&tuple_vals)
  {
    is_attr      = false;
    tuple_values = std::move(tuple_vals);
  }

  bool is_sub_query() const { return simple_sub_query != nullptr; }
  bool is_tuple_values() const { return tuple_values != nullptr; }
};

class FilterUnit
{
public:
  FilterUnit() = default;
  ~FilterUnit() {}

  void set_comp(CompOp comp) { comp_ = comp; }

  CompOp comp() const { return comp_; }

  void set_left(FilterObj &&obj) { left_ = std::move(obj); }
  void set_right(FilterObj &&obj) { right_ = std::move(obj); }

  FilterObj &&left() { return std::move(left_); }
  FilterObj &&right() { return std::move(right_); }
  void        set_conjunction_type(bool conjunction_type) { conjunction_type_ = conjunction_type; }
  bool        conjunction_type() const { return conjunction_type_; }

private:
  CompOp    comp_ = NO_OP;
  FilterObj left_;
  FilterObj right_;
  bool      conjunction_type_ = true;  // 如果和后面的表达式使用AND连接，就使用true,使用OR的话就是false
};

/**
 * @brief Filter/谓词/过滤语句
 * @ingroup Statement
 */
class FilterStmt
{
public:
  FilterStmt() = default;
  virtual ~FilterStmt();

public:
  const std::vector<FilterUnit *> &filter_units() const { return filter_units_; }

public:
  static RC create(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
      ConditionSqlNode *conditions, int condition_num, FilterStmt *&stmt,
      std::unordered_map<std::string, std::string> *alias_map         = nullptr,
      std::unordered_map<std::string, std::string> *outside_alias_map = nullptr);

  static RC create_filter_unit(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
      ConditionSqlNode &condition, FilterUnit *&filter_unit,
      std::unordered_map<std::string, std::string> *alias_map         = nullptr,
      std::unordered_map<std::string, std::string> *outside_alias_map = nullptr);

private:
  std::vector<FilterUnit *> filter_units_;  // 默认当前都是AND关系
};
